package com.epi;

import java.util.Random;

/**
 * @author translated from c++ by Blazheev Alexander
 */
public class ClosestIntSameBits {
    public static int set_bit(int x, int bit, boolean set_value) {
        return set_value ? x | (1 << bit) : x & ~(1 << bit);
    }

    public static int search(int x, int set_value, int default_value) {
        int index = 0, num = 0;
        while (((x >> index) & 1) != set_value) {
            ++index;
        }
        while (((x >> index) & 1) == set_value) {
            ++index;
            ++num;
        }
        if (index == 32) {
            return default_value;
        } else {
            x ^= (1 << index);
            --index;
            --num;
            for (int i = index; i >= num; --i) {
                x = set_bit(x, i, set_value != 0);
            }
            for (int i = num - 1; i >= 0; --i) {
                x = set_bit(x, i, set_value == 0);
            }
            return x;
        }
    }

    /*
    public static int closest_int_same_bits(int x) {
        int prev = search(x, 0, Integer.MIN_VALUE);
        int next = search(x, 1, Integer.MAX_VALUE);
        return Math.abs(x - prev) < Math.abs(x - next) ? prev : next;
    }
    */

    // @include
    public static long closest_int_same_bits(long x) {
        for (int i = 0; i < 63; ++i) {
            if ((((x >> i) & 1) ^ ((x >> (i + 1)) & 1)) != 0) {
                x ^= (1L << i) | (1L << (i + 1));  // swaps bit-i and bit-(i + 1)
                return x;
            }
        }

        // Throw error if all bits of x are 0 or 1
        throw new RuntimeException("all bits are 0 or 1");
    }
    // @exclude

    public static int count_bits_set_to_1(int x) {
        int count = 0;
        while (x != 0) {
            x &= (x - 1);
            ++count;
        }
        return count;
    }

    public static void main(String[] args) {
        Random r = new Random();
        long x;
        if (args.length == 1) {
            x = Long.parseLong(args[0]);
        } else {
            x = r.nextInt(Integer.MAX_VALUE);
        }
        try {
            long res = closest_int_same_bits(x);
            System.out.println(x + " " + res);
            assert(count_bits_set_to_1((int) x) == count_bits_set_to_1((int) res));
        } catch (Exception e) {
            System.out.println(x + " " + e.getMessage());
        }
    }
}
